#!/usr/bin/python3
# -*- coding: utf-8 -*-

import os
import sys
import time
import math
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from decimal import Decimal
import traceback

from api.position import update_symbol_info, reset_leverage
from api.market import  fetch_binance_ticker_data,fetch_binance_swap_candle_data

from functions import send_dingding_msg   # 钉钉可自行添加
from utils.notification import send_msg_for_position, send_wechat_work_msg,send_dataframe

from utils.commons import robust
#from rebalance.fee import  set_multiassetsmargin
from config import quant



# ===设置默认最大杠杆数，变相增加资金容量
# reset_leverage(quant.exchange, max_leverage=5)
# set_multiassetsmargin(quant.exchange, bool(True))  # 更改成联合保证金模式
#  移动止盈止损
profit_record = 0.2  # 盈利多少开始记录到移动止盈文件中(列如,设置成0.3,当前eth持仓盈利30个点,将进入移动止盈文件中)
profit_percentage = 0.22  # 移动止盈回撤多少平仓百分比(列如填写0.2,等于最高点回撤20%后止盈.0.45*0.2更灵活)
percentage = 0.08  # 外挂固定止损,防止极端(0.03等于3%止损,仓位亏损3个点就止损)
# 配置

# 机长顶针止盈止损
long_profit_record = 0.199  # 做多止盈阈值
short_profit_record = 0.199  # 做空止盈阈值
drawback = 0.2  # 移动止盈，回撤多少平仓百分比(列如填写0.2,等于回撤20%后止盈)
ban_hours = 12  # 止盈后拉黑时长(不拉黑可以设为0)
sleep_time = 10  # 每次循环休息秒数

# -坤滚动版止盈止损（默认滚动n为10，即只获取最近10根k线）
roll_long_profit_record = 0.3  # 做多止盈阈值
roll_short_profit_record = 0.3  # 做空止盈阈值
# 0.4的阈值，可以不错过绝大多数行情，曲线波动更大，（中大参数建议此阈值，当然具体需要结合自身策略）0.3的阈值不上不下，全看运气，0.2的阈值会让曲线更平稳，回撤降低，但是收益可能会下降。
roll_ban_hours = 24  # 止盈后拉黑时长(不拉黑可以设为0)
# sleep_time = 10  # 每次循环休息秒数
roll_n = 10  # 获取过去n个小时k线，建议10-24之间，各有利弊。根据实盘调控。 （不要超过100，防止api超权重）

#  钉钉id和key
robot_id = ''
secret_key = ''

# ===重试机制
def retry_wrapper(func, params, act_name='', sleep_seconds=3, retry_times=5):
    """
    需要在出错时不断重试的函数，例如和交易所交互，可以使用本函数调用。
    :param func: 需要重试的函数名
    :param params: func的参数
    :param act_name: 本次动作的名称
    :param sleep_seconds: 报错后的sleep时间
    :param retry_times: 为最大的出错重试次数
    :return:
    """

    for _ in range(retry_times):
        try:
            result = func(params=params)
            return result
        except Exception as e:
            print(act_name, '报错，报错内容：', str(e), '程序暂停(秒)：', sleep_seconds)
            send_wechat_work_msg(e)
            time.sleep(sleep_seconds)
    else:
        # send_wechat_work_msg(output_info)
        # send_dingding_and_raise_error(output_info)
        raise ValueError(act_name, '报错重试次数超过上限，程序退出。')


def get_min_order_quantity():
    # 初始化交易所
    exchange = quant.exchange

    # 获取交易规则
    data = exchange.fapiPublic_get_exchangeinfo()
    # 获取BUSD和USDI的交易对
    _symbol_list = [x for x in data['symbols'] if x['symbol'].endswith('BUSD') or x['symbol'].endswith('USDT')]

    # 获取需要的最小下单量数据
    min_qty_list = []
    for symbol in _symbol_list:
        min_qty_list.append({
            '合约': symbol['symbol'],
            '最小下单量': symbol['filters'][1]['minQty']
        })

    # 转成df
    new_df = pd.DataFrame(min_qty_list)
    return new_df


# 拆单函数
def split_order(max_one_order_amount, params, direction, price_precision, dingding_id, dingding_secret):
    # 获取币种最新价格
    exchange = quant.exchange
    # 检测是否存在挂单，避免需要平仓时，存在挂单。
    openOrders = binance_u_furture_get_openOrders(exchange)  # 查询当前所有挂单
    openOrders = pd.DataFrame(openOrders, dtype='float')
    # 整理数据
    openOrders.rename(columns={'symbol': '交易对', 'orderId': '系统订单号'}, inplace=True)
    print(openOrders)
    ii = 0
    if len(openOrders.index) != 0:
        for ind, row in openOrders.iterrows():
            ii += 1
            print('查询订单中', ind)
            symbol = row.iloc[1]
            binance_u_furture_DELETE_allOpenOrders(exchange, symbol)
            print(f'取消{symbol}存在的挂单成功')
    symbol_last_price = fetch_binance_ticker_data(exchange)
    symbol = params['symbol']
    total_amount = float(params['quantity'])

    # 根据持仓量计算出持仓的usdt数
    pos_amount_usdt = symbol_last_price[symbol] * total_amount
    # 根据某币种的总持仓usdt/最大下单usdt量，得到拆分后的下单次数
    order_num = math.floor(pos_amount_usdt / max_one_order_amount) + 1
    print(order_num)
    df_min_order = get_min_order_quantity()  # 获取最小下单量
    if order_num == 1:
        min_order_quantity = float(df_min_order.loc[df_min_order['合约'] == params['symbol']]['最小下单量'])
        if min_order_quantity < 1:
            min_order_quantity = len(str(min_order_quantity)) - 2  # 小数点后几位数
            rest_order_amount = total_amount
        else:
            min_order_quantity = 0  # # 大于1
            rest_order_amount = total_amount

        rest_order_amount = float(rest_order_amount)
        rest_order_amount = round(rest_order_amount, min_order_quantity)
        print(f'开始残单交易,共{order_num}份\t')
        # 最后残单下单
        params['quantity'] = rest_order_amount
        params['reduceOnly'] = True
        # 计算下单方向、价格
        if params['side'] == 'BUY':
            price = symbol_last_price[symbol] * 1.015
        else:
            params['side'] = 'SELL'
            price = symbol_last_price[symbol] * 0.985
        # price = float(f'{symbol_last_price[symbol]:.{price_precision[symbol]}f}')
        price = float(f'{price:.{price_precision[symbol]}f}')
        # 下单参数
        params = {
            'symbol': symbol,
            'side': params['side'],
            'type': 'LIMIT',
            'price': price,
            'quantity': params['quantity'],
            'clientOrderId': str(time.time()),
            'timeInForce': 'GTC',
            'reduceOnly': params['reduceOnly']
        }
        close_position = retry_wrapper(exchange.fapiPrivate_post_order, params, act_name='一次性小单处理')
        print(f'残单{close_position["symbol"]}平仓完成, 订单编号为{close_position["orderId"]}.')
        print(params)
        print(f"【监测】{params['symbol']}仓位已止损并添加至黑名单")

    elif order_num >= 2:  # 拆分下单数量大于1次
        # 计算每次下单的下单量
        if np.floor(total_amount / order_num) >= 2:
            each_order_amount = float(np.floor(total_amount / order_num))
            # df_min_order = get_min_order_quantity()
            min_order_quantity = float(df_min_order.loc[df_min_order['合约'] == params['symbol']]['最小下单量'])
            if min_order_quantity < 1:
                min_order_quantity = len(str(min_order_quantity)) - 2  # 小数点后几位数
                rest_order_amount = float(total_amount - each_order_amount * order_num)
                rest_order_amount = round(rest_order_amount, min_order_quantity)
            else:
                min_order_quantity = 0 # 大于1
                rest_order_amount = total_amount
                rest_order_amount = float(rest_order_amount - each_order_amount * order_num)
                rest_order_amount = round(rest_order_amount, min_order_quantity)
        else:
            # df_min_order = get_min_order_quantity()
            min_order_quantity = float(df_min_order.loc[df_min_order['合约'] == params['symbol']]['最小下单量'])
            each_order_amount = float(np.floor(total_amount / order_num / min_order_quantity) * min_order_quantity)
            each_order_amount = str(each_order_amount)  # 假设下单量1份0.0125,最小下单量限制0.001
            min_order_quantity = len(str(min_order_quantity)) - 2  # 小数点后几位数
            each_order_amount = float(each_order_amount[:(min_order_quantity) + 2])
            rest_order_amount = float(total_amount - each_order_amount * order_num)
            rest_order_amount = round(rest_order_amount, min_order_quantity)
        # 下单量
        print(f"碎单数:", {rest_order_amount})
        params['quantity'] = each_order_amount
        params = {
            'symbol': symbol,  # 币对
            'side': params['side'],  # sell
            'positionSide': params['positionSide'],
            'reduceOnly': True,  # 仅减仓,避免开出反向单
            'quantity': params['quantity'],
            'type': 'MARKET'
        }
        print(f'开始拆单交易,共拆成{order_num}份\t')
        order_num_demolition = 0
        for i in range(order_num):
            close_position = retry_wrapper(exchange.fapiPrivate_post_order, params, act_name='拆单处理中')
            print(
                f'第{i + 1}份{close_position["symbol"]}平仓完成 ,订单编号为{close_position["orderId"]}.')
            print(params)
            time.sleep(5)
            order_num_demolition = order_num_demolition + 1
            if order_num_demolition == order_num and rest_order_amount > 0:
                print(f'开始第{i + 2}份残单交易,\t')
                # 最后残单下单
                params['quantity'] = rest_order_amount
                params['reduceOnly'] = True
                # 计算下单方向、价格
                if params['side'] == 'BUY':
                    price = symbol_last_price[symbol] * 1.015
                else:
                    params['side'] = 'SELL'
                    price = symbol_last_price[symbol] * 0.985
                # price = float(f'{symbol_last_price[symbol]:.{price_precision[symbol]}f}')
                price = float(f'{price:.{price_precision[symbol]}f}')
                # if rest_order_amount * price > min_notional.get(symbol, 5):
                # print('quantity * price < 5')
                # quantity = 0
                # params = {
                #     'symbol': symbol,  # 币对
                #     'side': params['side'] , # sell
                #     'positionSide': params['pos_side'],
                #     'reduceOnly': True,  # 仅减仓,避免开出反向单
                #     'quantity': params['quantity'],
                #     'type': 'MARKET'
                # }
                # 下单参数
                params = {
                    'symbol': symbol,
                    'side': params['side'],
                    'type': 'LIMIT',
                    'price': price,
                    'quantity': params['quantity'],
                    'clientOrderId': str(time.time()),
                    'timeInForce': 'GTC',
                    'reduceOnly': params['reduceOnly']
                }
                close_position = retry_wrapper(exchange.fapiPrivate_post_order, params, act_name='碎单处理中')
                print(f'残单{close_position["symbol"]}平仓完成, 订单编号为{close_position["orderId"]}.')
                print(params)
                print(f"【监测】{params['symbol']}仓位已止损并添加至黑名单")
    # else:
    #     print('quantity * price < 5')
    send_wechat_work_msg(f"【监测】{direction}{close_position['symbol']}已平仓并添加至黑名单，订单编号{close_position['orderId']}.")
#     send_dingding_msg(
#         f"【监测】{direction}{close_position['symbol']}已平仓并添加至黑名单，订单编号为{close_position['orderId']}.",
#         dingding_id, dingding_secret)



# 检测固定止损,临时黑名单
def positionside(exchange, percentage, profit_percentage, max_one_order_amount, price_precision, profit_record, equity,
                 dingding_id, dingding_secret):
    try:
        data = exchange.fapiPrivateV2_get_account()['positions']
        position = [p for p in data if Decimal(p['initialMargin']) > 0]
        temporary_black_long_list = []
        temporary_black_short_list = []
        temporary_black_list = []
        formatted_positions = []
        add_time = datetime.now().strftime("%m/%d/%Y %H:%M")
        add_time1 = datetime.now().strftime("%m/%d/%Y %H:%M")
        '''以下部分可自行修改添加至黑名单的条件'''
        for pos in position:
            pos_side = pos['positionSide']  # 持仓方向
            margin = Decimal(pos['initialMargin'])  # 起始保证金
            profit = Decimal(pos['unrealizedProfit'])  # 持仓未实现盈亏
            pos_amount = Decimal(pos['positionAmt'])  # 持仓数量
            # leverage = Decimal(pos['leverage'])  # 杠杆
            entryPrice = Decimal(pos['entryPrice'])  # 持仓成本
            Proportion = (abs(pos_amount) * entryPrice) / Decimal(equity)
            # 持仓占比计算
            # rtn = ((margin + profit) / margin - 1) / leverage  # 持仓盈亏计算
            rtn = Decimal(profit) / (abs(pos_amount) * entryPrice)  # 持仓盈亏计算
            side = 'SELL' if pos_amount > 0 else 'BUY'
            condition = profit < 0 and abs(rtn) >= float(percentage)  # 如果当前盈利为负数，且大于触发百分百，币种进黑名单
            # mark = profit > 0 and abs(rtn) >= percentage  # 如果当前盈利为正数，且大于触发百分比，币种进黑名单

            add_time2 = datetime.now().strftime("%m/%d/%Y %H:%M")
            temp_list_rtn = []

            #  记录持仓盈亏
            temp_list_rtn.append(pos['symbol'])
            temp_list_rtn.append(round(rtn, 4))
            temp_list_rtn.append(add_time2)
            temporary_black_list.append(temp_list_rtn)


            # temporary_black_list1.append(temp_list_rtn)
            if float(pos_amount) > 0:
                direction = "做多"
                formatted_positions.append({
                    'symbol': pos['symbol'],
                    'direction': direction,
                    'entryPrice': entryPrice,
                    'profit': profit,
                    'Proportion': Proportion,
                    'rtn': rtn
                })
                '''以上部分可自行修改添加至黑名单的条件'''

                temp_list = []

                if condition:
                    temp_list.append(pos['symbol'])
                    temp_list.append(add_time)
                    temporary_black_long_list.append(temp_list)

                    params = {
                        'symbol': pos['symbol'],  # 币对
                        'side': side,  # sell
                        'positionSide': pos_side,
                        'reduceOnly': True,  # 仅减仓,避免开出反向单
                        'quantity': abs(pos_amount),
                        'type': 'MARKET'
                    }

                    close_position = exchange.fapiPrivate_post_order(params=params)  # 亏损的币种先减仓拉入黑名单
                    # send_dingding_msg(
                    #     f"【监测】{direction}{close_position['symbol']}仓位已止损并添加至黑名单，订单编号为{close_position['orderId']}.",
                    #     dingding_id, dingding_secret)
                    send_wechat_work_msg(f"【监测】{direction}{close_position['symbol']}仓位已止损并添加至黑名单，订单编号为{close_position['orderId']}.")
                    split_order(max_one_order_amount, params, direction, price_precision, dingding_id,
                                dingding_secret)  # 平仓
            if float(pos_amount) < 0:
                direction = "做空"
                formatted_positions.append({
                    'symbol': pos['symbol'],
                    'direction': direction,
                    'entryPrice': entryPrice,
                    'profit': profit,
                    'Proportion': Proportion,
                    'rtn': rtn
                })
                '''以上部分可自行修改添加至黑名单的条件'''

                temp_list1 = []

                if condition:
                    temp_list1.append(pos['symbol'])
                    temp_list1.append(add_time1)
                    temporary_black_short_list.append(temp_list1)

                    params = {
                        'symbol': pos['symbol'],
                        'side': side,
                        'positionSide': pos_side,
                        'reduceOnly': True,  # 仅减仓,避免开出反向单
                        'quantity': abs(pos_amount),
                        'type': 'MARKET'
                    }

                    close_position = exchange.fapiPrivate_post_order(params=params)  # 亏损的币种先减仓拉入黑名单
                    # send_dingding_msg(
                    #     f"【监测】{direction}{close_position['symbol']}仓位已止损并添加至黑名单，订单编号为{close_position['orderId']}.",
                    #     dingding_id, dingding_secret)
                    send_wechat_work_msg( f"【监测】{direction}{close_position['symbol']}仓位已止损并添加至黑名单，订单编号为{close_position['orderId']}.")
                    split_order(max_one_order_amount, params, direction, price_precision, dingding_id,
                                dingding_secret)  # 亏损的币种先减仓拉入黑名单(拆单操作)
        # 对收集的持仓进行排序，根据占比大小降序排列，并取前十个
        top_formatted_positions = sorted(formatted_positions, key=lambda x: x['Proportion'], reverse=True)[:10]

        # 输出排名前十的持仓信息
        for pos in top_formatted_positions:
            print(f"持仓: {pos['symbol']}, {pos['direction']}, 成本:{round(pos['entryPrice'], 6)}, "
                  f"量: {round(pos['profit'], 4)},占比{round(pos['Proportion'], 4) * 100}%, 盈亏: {round(pos['rtn'], 4) * 100}%")

    # exit()
        temp_df = pd.DataFrame(temporary_black_long_list, columns=['symbol', 'release_time'])
        temp_df['release_time'] = pd.to_datetime(temp_df['release_time'])
        temp_df['release_time'] = temp_df['release_time'] + timedelta(hours=+48)  # 币种添加至黑名单的时间加24小时

        temp_df1 = pd.DataFrame(temporary_black_short_list, columns=['symbol', 'release_time'])
        temp_df1['release_time'] = pd.to_datetime(temp_df1['release_time'])
        temp_df1['release_time'] = temp_df1['release_time'] + timedelta(hours=+48)  # 币种添加至黑名单的时间加24小时

        temp_df2 = pd.DataFrame(temporary_black_list, columns=['symbol', 'profit_and_loss', 'release_time'])
        temp_df2['release_time'] = pd.to_datetime(temp_df2['release_time'])

        temp_df3 = pd.DataFrame(columns=['symbol', 'profit_and_loss', 'release_time', 'value'])
        # temp_df3['release_time'] = pd.to_datetime(temp_df3['release_time'])
        # temp_df3 = pd.DataFrame(temporary_black_list1, columns=['symbol', 'profit_and_loss', 'release_time'])
        # temp_df3['release_time'] = pd.to_datetime(temp_df3['release_time'])

        try:
            df = pd.read_csv('temporary_black_long_list.csv', parse_dates=['release_time'], index_col=[0])
            df = df.append(temp_df)  # 添加新的币种至做多黑名单
            df.drop_duplicates(subset='symbol',keep='last', inplace=True)  # 去掉重复加进的币种
            # print(df[df['release_time'] > add_time])
            df = df[df['release_time'] > add_time]  # 解放时间 > 当前时间，则币种从做多黑名单里删除
            df.to_csv('temporary_black_long_list.csv')
        except:
            df = temp_df
            df.to_csv('temporary_black_long_list.csv')

        try:
            df1 = pd.read_csv('temporary_black_short_list.csv', parse_dates=['release_time'], index_col=[0])
            df1 = df1.append(temp_df1)  # 添加新的币种至做空黑名单
            df1.drop_duplicates(subset='symbol',keep='last', inplace=True)  # 去掉重复加进的币种
            df1 = df1[df1['release_time'] > add_time1]  # 解放时间 > 当前时间，则币种从做空黑名单里删除
            df1.to_csv('temporary_black_short_list.csv')
        except:
            df1 = temp_df1
            df1.to_csv('temporary_black_short_list.csv')
        # print(df)
        # print(df1)
        try:
            df_old = pd.read_csv("temporary_black_list.csv", parse_dates=['release_time'], index_col=[0])  # 读取持仓盈亏表
            df_new = temp_df2
            symbol_list = df_new['symbol']
            df3 = df_old.append(temp_df2)  # 新旧盈亏合并
            df3.sort_values(by=['profit_and_loss'], inplace=True, ascending=False)  # 以收益排序
            df3.drop_duplicates(['symbol'], inplace=True)  # 删除盈亏较少的排序
            df3 = df3[df3['symbol'].isin(symbol_list)]
        except:
            # except Exception as e:
            #     print(e)
            df3 = temp_df2
        print("最大持仓盈亏表")
        df3.to_csv("temporary_black_list.csv")
        try:
            df2 = pd.read_csv("temporary_black_list.csv", parse_dates=['release_time'], index_col=[0])  # 读取差值表
            df2 = df2.append(temp_df2, ignore_index=True, sort=False)  # 合并最新币单
            df2.sort_values(by=['symbol', 'profit_and_loss'], inplace=True, ascending=[True, True])  # 排序
            df2["profit_and_loss"] = pd.to_numeric(df2["profit_and_loss"], errors='coerce')  # 格式转换
            df2 = df2[~(df2['profit_and_loss'] < 0)]  # 去掉持仓未盈利的(亏损的币种)
            df2['value'] = df2.groupby('symbol')['profit_and_loss'].diff()  # 求差值
            df2.drop_duplicates(['symbol'], keep='last', inplace=True)  # 留下最新差值列表
            df2 = df2[~(df2['profit_and_loss'] <= profit_record)]  # 涨幅小于设定的，如50%不进行移动止盈
            profit_percentage = profit_record * profit_percentage
            df2 = df2[df2['value'] > profit_percentage]  # 删除小于价差数值的行,留下需要止盈的币种
        except:
            df2 = temp_df3  # 添加一个列表

        df2.to_csv("temporary_black_list_percentage.csv")
        # print(df)
        # print(df1)
        print(df2)
        print(df3)
    except Exception as e:
        print('未有添加币种或异常提示:', e)
    time.sleep(1)

# 滚动逃顶
def positionside_gundongtaoding(balance, df_current, roll_long_profit_record, roll_short_profit_record,equity,
                              max_one_order_amount, price_precision,
                              roll_ban_hours, robot_id, secret_key):
    try:
        data = balance['positions']
        position = [p for p in data if Decimal(p['initialMargin']) > 0]
        # 持仓占比计算
        temporary_black_long_list = []
        temporary_black_short_list = []
        formatted_positions = []
        add_time = datetime.now().strftime("%m/%d/%Y %H:%M")

        '''以下部分可自行修改添加至黑名单的条件'''
        for pos in position:
            long_scrolling = df_current.loc[pos['symbol'], '最高价跌幅价差值']
            sell_scrolling = df_current.loc[pos['symbol'], '最低价跌幅价差值']

            pos_amount = Decimal(pos['positionAmt'])  # 持仓数量
            # leverage = Decimal(pos['leverage'])  # 杠杆
            entryPrice = Decimal(pos['entryPrice'])  # 持仓成本
            Proportion = (abs(pos_amount) * entryPrice) / Decimal(equity)

            pos_side = pos['positionSide']  # 持仓方向
            profit = Decimal(pos['unrealizedProfit'])  # 持仓未实现盈亏
            pos_amount = Decimal(pos['positionAmt'])  # 持仓数量
            entryPrice = Decimal(pos['entryPrice'])  # 持仓成本

            rtn = Decimal(profit) / (abs(pos_amount) * entryPrice)  # 持仓盈亏计算
            side = 'SELL' if pos_amount > 0 else 'BUY'


            if float(pos_amount) > 0:   # 判断做多是否需要止盈
                direction = "做多"
                formatted_positions.append({
                    'symbol': pos['symbol'],
                    'direction': direction,
                    'entryPrice': entryPrice,
                    'profit': profit,
                    'Proportion': Proportion,
                    'rtn': rtn,
                    'long_scrolling': long_scrolling
                })

                # formatted_positions.append(
                #     f"持仓: {pos['symbol']}, {direction}, 成本:{round(entryPrice, 6)}, "
                #     f"量: {round(profit, 4)}, 盈亏: {round(rtn, 4) * 100}%, 做多滚动回撤值：{round(Decimal(long_scrolling), 4) * 100}%")
                # '''以上部分可自行修改添加至黑名单的条件'''

                temp_list = []

                if long_scrolling > roll_long_profit_record :

                    #   加入做多黑名单
                    temp_list.append(pos['symbol'])
                    temp_list.append(add_time)
                    temporary_black_long_list.append(temp_list)

                    params = {
                        'symbol': pos['symbol'],  # 币对
                        'side': side,  # sell
                        'positionSide': pos_side,
                        'reduceOnly': True,  # 仅减仓,避免开出反向单
                        'quantity': abs(pos_amount),
                        'type': 'MARKET'
                    }


                    split_order(max_one_order_amount, params, direction, price_precision, robot_id, secret_key)  # 平仓


            if float(pos_amount) < 0:   # 判断做空是否需要止盈
                direction = "做空"
                formatted_positions.append({
                    'symbol': pos['symbol'],
                    'direction': direction,
                    'entryPrice': entryPrice,
                    'profit': profit,
                    'Proportion': Proportion,
                    'rtn': rtn,
                    'long_scrolling': sell_scrolling
                })
                '''以上部分可自行修改添加至黑名单的条件'''
                temp_list1 = []

                if sell_scrolling > roll_short_profit_record :

                    #   加入做空黑名单
                    temp_list1.append(pos['symbol'])
                    temp_list1.append(add_time)
                    temporary_black_short_list.append(temp_list1)

                    params = {
                        'symbol': pos['symbol'],
                        'side': side,
                        'positionSide': pos_side,
                        'reduceOnly': True,  # 仅减仓,避免开出反向单
                        'quantity': abs(pos_amount),
                        'type': 'MARKET'
                    }

                    split_order(max_one_order_amount, params, direction, price_precision, robot_id, secret_key)  # 平仓
        # 对收集的持仓进行排序，根据占比大小降序排列，并取前十个
        top_formatted_positions = sorted(formatted_positions, key=lambda x: x['Proportion'], reverse=True)[:10]

        # 输出排名前十的持仓信息
        for pos in top_formatted_positions:
            print(f"持仓: {pos['symbol']}, {pos['direction']}, 成本:{round(pos['entryPrice'], 6)}, "
                  f"量: {round(pos['profit'], 4)},盈亏{round(pos['rtn'], 4) * 100}%,"
                  f"占比{round(pos['Proportion'], 4) * 100}% , {pos['direction']}滚动回撤值: {round(Decimal(pos['long_scrolling']) * 100, 4)}%")

        #
        temp_df_long = pd.DataFrame(temporary_black_long_list, columns=['symbol', 'release_time'])
        temp_df_long['release_time'] = pd.to_datetime(temp_df_long['release_time'])
        temp_df_long['release_time'] = temp_df_long['release_time'] + timedelta(hours=+ roll_ban_hours)  # 币种添加至黑名单的时间

        temp_df_short = pd.DataFrame(temporary_black_short_list, columns=['symbol', 'release_time'])
        temp_df_short['release_time'] = pd.to_datetime(temp_df_short['release_time'])
        temp_df_short['release_time'] = temp_df_short['release_time'] + timedelta(hours=+ roll_ban_hours)  # 币种添加至黑名单的时间



        try:
            df = pd.read_csv('temporary_black_long_list.csv', parse_dates=['release_time'], index_col=[0])
            df = df.append(temp_df_long)  # 添加新的币种至做多黑名单
            df.drop_duplicates(subset='symbol', inplace=True)  # 去掉重复加进的币种
            df = df[df['release_time'] > add_time]  # 解放时间 > 当前时间，则币种从做多黑名单里删除
            df.to_csv('temporary_black_long_list.csv')
        except:
            df = temp_df_long
            df.to_csv('temporary_black_long_list.csv')

        try:
            df1 = pd.read_csv('temporary_black_short_list.csv', parse_dates=['release_time'], index_col=[0])
            df1 = df1.append(temp_df_short)  # 添加新的币种至做空黑名单
            df1.drop_duplicates(subset='symbol', inplace=True)  # 去掉重复加进的币种
            df1 = df1[df1['release_time'] > add_time]  # 解放时间 > 当前时间，则币种从做空黑名单里删除
            df1.to_csv('temporary_black_short_list.csv')
        except:
            df1 = temp_df_short
            df1.to_csv('temporary_black_short_list.csv')



    except Exception as e:
        print('未有添加币种或异常提示:', e)
    time.sleep(1)


# 顶针监测
def positionside_dingzhen(balance, df_current, long_profit_record, short_profit_record, equity,drawback,
                          max_one_order_amount, price_precision,ban_hours, robot_id, secret_key):
    try:
        data = balance['positions']
        position = [p for p in data if Decimal(p['initialMargin']) > 0]

        temporary_black_long_list = []
        temporary_black_short_list = []
        formatted_positions = []
        add_time = datetime.now().strftime("%m/%d/%Y %H:%M")

        '''以下部分可自行修改添加至黑名单的条件'''
        for pos in position:
            dingzhen = df_current.loc[pos['symbol'], '丁针长度']
            current_drawback = df_current.loc[pos['symbol'], '回落幅度']

            pos_amount = Decimal(pos['positionAmt'])  # 持仓数量
            # leverage = Decimal(pos['leverage'])  # 杠杆
            entryPrice = Decimal(pos['entryPrice'])  # 持仓成本
            Proportion = (abs(pos_amount) * entryPrice) / Decimal(equity)
            pos_side = pos['positionSide']  # 持仓方向
            profit = Decimal(pos['unrealizedProfit'])  # 持仓未实现盈亏
            pos_amount = Decimal(pos['positionAmt'])  # 持仓数量
            entryPrice = Decimal(pos['entryPrice'])  # 持仓成本

            rtn = Decimal(profit) / (abs(pos_amount) * entryPrice)  # 持仓盈亏计算
            side = 'SELL' if pos_amount > 0 else 'BUY'


            if float(pos_amount) > 0:   # 判断做多是否需要止盈
                direction = "做多"
                # formatted_positions.append(
                #     f"持仓: {pos['symbol']}, {direction}, 成本:{round(entryPrice, 6)}, "
                #     f"量: {round(profit, 4)}, 盈亏: {round(rtn, 4) * 100}%, 丁针长度：{round(Decimal(dingzhen), 4) * 100}%")
                #
                formatted_positions.append({
                    'symbol': pos['symbol'],
                    'direction': direction,
                    'entryPrice': entryPrice,
                    'profit': profit,
                    'Proportion': Proportion,
                    'rtn': rtn,
                    'dingzhen': dingzhen
                })
                '''以上部分可自行修改添加至黑名单的条件'''
                temp_list = []

                if dingzhen > long_profit_record and current_drawback > drawback:

                    #   加入做多黑名单
                    temp_list.append(pos['symbol'])
                    temp_list.append(add_time)
                    temporary_black_long_list.append(temp_list)

                    params = {
                        'symbol': pos['symbol'],  # 币对
                        'side': side,  # sell
                        'positionSide': pos_side,
                        'reduceOnly': True,  # 仅减仓,避免开出反向单
                        'quantity': abs(pos_amount),
                        'type': 'MARKET'
                    }


                    split_order(max_one_order_amount, params, direction, price_precision, robot_id, secret_key)  # 平仓


            if float(pos_amount) < 0:   # 判断做空是否需要止盈
                direction = "做空"
                formatted_positions.append({
                    'symbol': pos['symbol'],
                    'direction': direction,
                    'entryPrice': entryPrice,
                    'profit': profit,
                    'Proportion': Proportion,
                    'rtn': rtn,
                    'dingzhen': dingzhen
                })
                # formatted_positions.append(
                #     f"持仓: {pos['symbol']}, {direction}, 成本:{round(entryPrice, 6)}, "
                #     f"量: {round(profit, 4)}, 盈亏: {round(rtn, 4) * 100}%, 丁针长度：{round(Decimal(dingzhen), 4) * 100}%")
                # '''以上部分可自行修改添加至黑名单的条件'''


                temp_list1 = []

                if dingzhen > short_profit_record and current_drawback > drawback:

                    #   加入做空黑名单
                    temp_list1.append(pos['symbol'])
                    temp_list1.append(add_time)
                    temporary_black_short_list.append(temp_list1)

                    params = {
                        'symbol': pos['symbol'],
                        'side': side,
                        'positionSide': pos_side,
                        'reduceOnly': True,  # 仅减仓,避免开出反向单
                        'quantity': abs(pos_amount),
                        'type': 'MARKET'
                    }

                    split_order(max_one_order_amount, params, direction, price_precision, robot_id, secret_key)  # 平仓

        # 对收集的持仓进行排序，根据占比大小降序排列，并取前十个
        top_formatted_positions = sorted(formatted_positions, key=lambda x: x['Proportion'], reverse=True)[:10]

        # 输出排名前十的持仓信息
        for pos in top_formatted_positions:
            print(f"持仓: {pos['symbol']}, {pos['direction']}, 成本:{round(pos['entryPrice'], 6)}, "
                  f"量: {round(pos['profit'], 4)},盈亏{round(pos['rtn'], 4) * 100}%,"
                  f"占比{round(pos['Proportion'], 4) * 100}% , 丁针长度: {round(Decimal(pos['dingzhen']) * 100, 4)}%")

        temp_df_long = pd.DataFrame(temporary_black_long_list, columns=['symbol', 'release_time'])
        temp_df_long['release_time'] = pd.to_datetime(temp_df_long['release_time'])
        temp_df_long['release_time'] = temp_df_long['release_time'] + timedelta(hours=+ ban_hours)  # 币种添加至黑名单的时间

        temp_df_short = pd.DataFrame(temporary_black_short_list, columns=['symbol', 'release_time'])
        temp_df_short['release_time'] = pd.to_datetime(temp_df_short['release_time'])
        temp_df_short['release_time'] = temp_df_short['release_time'] + timedelta(hours=+ ban_hours)  # 币种添加至黑名单的时间



        try:
            df = pd.read_csv('temporary_black_long_list.csv', parse_dates=['release_time'], index_col=[0])
            df = df.append(temp_df_long)  # 添加新的币种至做多黑名单
            df.drop_duplicates(subset='symbol', inplace=True)  # 去掉重复加进的币种
            df = df[df['release_time'] > add_time]  # 解放时间 > 当前时间，则币种从做多黑名单里删除
            df.to_csv('temporary_black_long_list.csv')
        except:
            df = temp_df_long
            df.to_csv('temporary_black_long_list.csv')

        try:
            df1 = pd.read_csv('temporary_black_short_list.csv', parse_dates=['release_time'], index_col=[0])
            df1 = df1.append(temp_df_short)  # 添加新的币种至做空黑名单
            df1.drop_duplicates(subset='symbol', inplace=True)  # 去掉重复加进的币种
            df1 = df1[df1['release_time'] > add_time]  # 解放时间 > 当前时间，则币种从做空黑名单里删除
            df1.to_csv('temporary_black_short_list.csv')
        except:
            df1 = temp_df_short
            df1.to_csv('temporary_black_short_list.csv')



    except Exception as e:
        print('未有添加币种或异常提示:', e)
    time.sleep(1)


# 检测持仓盈亏价差,并移动止盈,拉入黑名单48小时
def position_profit(exchange, max_one_order_amount, price_precision, equity, dingding_id, dingding_secret):
    df_now = pd.read_csv('temporary_black_list_percentage.csv', parse_dates=['release_time'], index_col=[0])  # 读取差值表
    temporary_black_long_list = []
    temporary_black_short_list = []
    formatted_positions = []
    add_time = datetime.now().strftime("%m/%d/%Y %H:%M")
    for each in df_now.groupby('symbol'):
        # print(each[1]["symbol"].iloc[0])
        row = each[1]["symbol"].iloc[0]
        data = exchange.fapiPrivateV2_get_account()['positions']
        pos = [p for p in data if p['symbol'] == row]
        pos_side = pos[0]['positionSide']
        margin = Decimal(pos[0]['initialMargin'])
        profit = Decimal(pos[0]['unrealizedProfit'])
        pos_amount = Decimal(pos[0]['positionAmt'])
        leverage = Decimal(pos[0]['leverage'])

        entryPrice = Decimal(pos[0]['entryPrice'])  # 持仓成本
        Proportion = (abs(pos_amount) * entryPrice) / Decimal(equity)
        rtn = Decimal(profit) / (abs(pos_amount) * entryPrice)  # 持仓盈亏计算
        # rtn = ((margin + profit) / margin - 1) / leverage
        side = 'SELL' if pos_amount > 0 else 'BUY'

        if float(pos_amount) > 0:
            direction = "做多盈利"
            print(
                f"持仓: {pos[0]['symbol']}, {direction}, 成本:{round(entryPrice, 6)}, 量: {round(profit, 4)},占比{round(Proportion, 4) * 100}%, 盈亏: {round(rtn, 4) * 100}%, 平仓中")
            '''以上部分可自行修改添加至黑名单的条件'''
            temp_list = []
            temp_list.append(pos[0]['symbol'])
            temp_list.append(add_time)
            temporary_black_long_list.append(temp_list)
            params = {
                'symbol': pos[0]['symbol'],
                'side': side,
                'positionSide': pos_side,
                'reduceOnly': True,  # 仅减仓,避免开出反向单
                'quantity': abs(pos_amount),
                'type': 'MARKET'
            }

            close_position = split_order(max_one_order_amount, params)  # 亏损的币种先减仓拉入黑名单
            # send_dingding_msg(
            #     f"【监测】{direction}{close_position['symbol']}仓位已止盈并添加至黑名单，恭喜老板大赚[鼓掌][鼓掌][鼓掌][鼓掌][鼓掌][666][666][666][666][666],订单编号为{close_position['orderId']}.",
            #     dingding_id, dingding_secret)
            send_wechat_work_msg( f"【监测】{direction}{close_position['symbol']}仓位已止盈并添加至黑名单，恭喜老板大赚[鼓掌][鼓掌][鼓掌][鼓掌][鼓掌][666][666][666][666][666],订单编号为{close_position['orderId']}.")
            split_order(max_one_order_amount, params, direction, price_precision, dingding_id,
                        dingding_secret)  # 亏损的币种先减仓拉入黑名单(拆单操作)

            temp_df = pd.DataFrame(temporary_black_long_list, columns=['symbol', 'release_time'])
            temp_df['release_time'] = pd.to_datetime(temp_df['release_time'])
            temp_df['release_time'] = temp_df['release_time'] + timedelta(hours=+48)  # 币种添加至黑名单的时间加24小时

            df_long = pd.read_csv('temporary_black_long_list.csv', parse_dates=['release_time'], index_col=[0])
            df_long = df_long.append(temp_df)  # 添加新的币种至做多黑名单
            df_long.drop_duplicates(subset='symbol',keep='last', inplace=True)  # 去掉重复加进的币种
            df_long = df_long[df_long['release_time'] > add_time]  # 解放时间 > 当前时间，则币种从做多黑名单里删除
            df_long.to_csv('temporary_black_long_list.csv')
            print('做多止盈成功,添加入,动态黑名单:')
            print(df_long)

            symbol = pos[0]['symbol']
            df1 = pd.read_csv('temporary_black_list_percentage.csv', parse_dates=['value'], index_col=[0])
            # df1 = df1[df1['symbol'] == pos[0]['symbol']]  # 止盈后，则币种持仓盈亏价差名单里删除
            df1 = df1[~df1['symbol'].isin([symbol])]
            # df2 = df2[df2['symbol'] == symbol]  # 止盈后，则币种持仓盈亏名单里删除
            print(df1)
            df1.to_csv('temporary_black_list_percentage.csv')
            df2 = pd.read_csv('temporary_black_list.csv', parse_dates=['profit_and_loss'], index_col=[0])
            df2 = df2[~df2['symbol'].isin([symbol])]
            # df2 = df2[df2['symbol'] == symbol]  # 止盈后，则币种持仓盈亏名单里删除
            df2.to_csv('temporary_black_list.csv')

        if float(pos_amount) < 0:
            direction = "做空盈利"
            print(
                f"持仓: {pos[0]['symbol']}, {direction}, 成本:{round(entryPrice, 6)}, 量: {round(profit, 4)},占比{round(Proportion, 4) * 100}%, 盈亏: {round(rtn, 4) * 100}%, 平仓中")
            '''以上部分可自行修改添加至黑名单的条件'''
            temp_list1 = []
            temp_list1.append(pos[0]['symbol'])
            temp_list1.append(add_time)
            temporary_black_short_list.append(temp_list1)
            params = {
                'symbol': pos[0]['symbol'],
                'side': side,
                'positionSide': pos_side,
                'reduceOnly': True,  # 仅减仓,避免开出反向单
                'quantity': abs(pos_amount),
                'type': 'MARKET'
            }

            close_position = exchange.fapiPrivate_post_order(params=params)  # 亏损的币种先减仓拉入黑名单
            # send_dingding_msg(
            #     f"【监测】{direction}{close_position['symbol']}仓位已止盈并添加至黑名单，恭喜老板大赚[鼓掌][鼓掌][鼓掌][鼓掌][鼓掌][666][666][666][666][666]，订单编号为{close_position['orderId']}.",
            #     dingding_id, dingding_secret)
            send_wechat_work_msg(f"【监测】{direction}{close_position['symbol']}仓位已止盈并添加至黑名单，恭喜老板大赚[鼓掌][鼓掌][鼓掌][鼓掌][鼓掌][666][666][666][666][666]，订单编号为{close_position['orderId']}.")
            split_order(max_one_order_amount, params, direction, price_precision, dingding_id,
                        dingding_secret)  # 亏损的币种先减仓拉入黑名单(拆单操作)

            temp_df1 = pd.DataFrame(temporary_black_short_list, columns=['symbol', 'release_time'])
            temp_df1['release_time'] = pd.to_datetime(temp_df1['release_time'])
            temp_df1['release_time'] = temp_df1['release_time'] + timedelta(hours=+48)  # 币种添加至黑名单的时间加24小时

            df_short = pd.read_csv('temporary_black_short_list.csv', parse_dates=['release_time'], index_col=[0])
            df_short = df_short.append(temp_df1)  # 添加新的币种至做空黑名单
            df_short.drop_duplicates(subset='symbol',keep='last', inplace=True)  # 去掉重复加进的币种
            df_short = df_short[df_short['release_time'] > add_time]  # 解放时间 > 当前时间，则币种从做空黑名单里删除
            df_short.to_csv('temporary_black_short_list.csv')
            print('做空止盈成功,添加入,动态黑名单:')
            print(df_short)

            symbol = pos[0]['symbol']
            df1 = pd.read_csv('temporary_black_list_percentage.csv', parse_dates=['value'], index_col=[0])
            # df1 = df1[df1['symbol'] == pos[0]['symbol']]  # 止盈后，则币种持仓盈亏价差名单里删除
            df1 = df1[~df1['symbol'].isin([symbol])]
            # df2 = df2[df2['symbol'] == symbol]  # 止盈后，则币种持仓盈亏名单里删除
            print(df1)
            df1.to_csv('temporary_black_list_percentage.csv')
            df2 = pd.read_csv('temporary_black_list.csv', parse_dates=['profit_and_loss'], index_col=[0])
            df2 = df2[~df2['symbol'].isin([symbol])]
            # df2 = df2[df2['symbol'] == symbol]  # 止盈后，则币种持仓盈亏名单里删除
            df2.to_csv('temporary_black_list.csv')

    time.sleep(1)

def binance_u_furture_get_openOrders(exchange):
    """
    查看当前全部挂单
    """
    openOrders_info = retry_wrapper(exchange.fapiPrivateGetOpenOrders, params={}, act_name='查看当前全部挂单')

    return openOrders_info


def binance_u_furture_DELETE_allOpenOrders(exchange, symbol):
    """
    查看当前全部挂单
    """
    DELETE_allOpenOrders = retry_wrapper(exchange.fapiPrivateDeleteAllOpenOrders, params={'symbol': symbol},
                                         act_name='查看当前全部挂单')

    return DELETE_allOpenOrders

def run():
    # ====初始化
    quant.initialize()

    while True:
        # ===加载市场信息
        quant.load_market()
        # =====设置参数
        exchange = quant.exchange
        symbol_list = quant.symbol_list
        min_notional = quant.min_notional
        price_precision = quant.price_precision
        trade_ratio = quant.trade_ratio
        max_one_order_amount = quant.max_one_order_amount
        dingding_id = robot_id
        dingding_secret = secret_key
        # profit_percentage = quant.profit_percentage

        balance = robust(exchange.fapiPrivateV2_get_account, func_name='fapiPrivateV2_get_account')  # 获取账户净值
        equity = float(balance['totalWalletBalance'])
        trade_usdt = equity * trade_ratio
        # trade_usdt = 100000
        print('【1】-----当前账户持净值统计-----')
        print('账户净值:', equity, '杠杆:', trade_ratio, '实际净值:', trade_usdt)
        print('移动止盈触发百分比:', str(round(profit_record * 100, 1)) + '%触发',
              '回调' + str(round(profit_percentage * 100, 1)) + '%止盈', '外挂固定止损:',
              str(round(percentage * 100, 1)) + '%')
        #send_wechat_work_msg(f"账户净值:,{equity},杠杆:{trade_ratio},实际净值:{trade_usdt}")
        # =====获取账户的实际持仓
        print('【2】-----当前账户持仓量统计-----')
        symbol_info = update_symbol_info(exchange, symbol_list)
        df_current = symbol_info[symbol_info['当前持仓量'] != 0]
        df_current = df_current.copy()
        symbol_list = df_current.index.tolist()
        now_time = datetime.now().replace(second=0, microsecond=0)

        n = roll_n  # 定义过去n个数据点（例如10个小时）
        for symbol in symbol_list:
            res = fetch_binance_swap_candle_data(exchange, symbol, now_time, limit=n)

            last_open_value = res[1]['open'].iloc[-1]
            last_high_value = res[1]['high'].iloc[-1]
            last_low_value = res[1]['low'].iloc[-1]
            current_price = res[1]['close'].iloc[-1]
            df_current.loc[symbol, '本小时open'] = last_open_value
            df_current.loc[symbol, '本小时high'] = last_high_value
            df_current.loc[symbol, '本小时low'] = last_low_value
            df_current.loc[symbol, '最新价格'] = current_price
            df_current['丁针长度'] = np.where(
                df_current['当前持仓量'] > 0,
                (df_current['本小时high'] - df_current['本小时open']) / df_current['本小时open'],
                (df_current['本小时open'] - df_current['本小时low']) / df_current['本小时open']
            )
            df_current['回落幅度'] = np.where(
                df_current['当前持仓量'] > 0,
                (df_current['本小时high'] - df_current['最新价格']) / df_current['本小时open'],
                (df_current['最新价格'] - df_current['本小时low']) / df_current['本小时open'])

        # 最高价跌幅滚动版max
            df_candle_data = res[1]  # 假设res[1]是返回的DataFrame

            # 获取过去n小时的数据（不包括当前小时）
            past_n_hour_high = df_candle_data['high'].max()  # 计算过去n小时的最高价
            current_price = df_candle_data['close'].iloc[-1]  # 当前价格

        # 最低价跌幅滚动版max
            past_n_hour_low = df_candle_data['low'].min()  # 包括当前小时在内的过去n小时的最低价

            # 计算当前收盘价与过去n小时内的最高价之间的差价比
            df_current.loc[symbol, f'{n}小时最高价跌幅价差比'] = (past_n_hour_high - current_price) / current_price

            # 计算当前收盘价与包括当前小时在内的过去n小时内的最低价之间的差价比
            df_current.loc[symbol, f'{n}小时最低价跌幅价差比'] = abs((past_n_hour_low - current_price) / current_price)

            df_current.loc[symbol, '最高价跌幅价差值'] = \
            df_current.loc[df_current.index == symbol, f'{n}小时最高价跌幅价差比'].rolling(window=n,
                                                                                             min_periods=1).max().iloc[
                -1]
            df_current.loc[symbol, '最低价跌幅价差值'] = \
            df_current.loc[df_current.index == symbol, f'{n}小时最低价跌幅价差比'].rolling(window=n,
                                                                                             min_periods=1).max().iloc[
                -1]

        print(df_current, '\n')


        # 监测持仓币数，大于7个，就取消掉其它所有挂单（为次高频策略准备，一般不需要用到）
        # Litter = len(symbol_info[symbol_info['当前持仓量'] != 0])
        # if Litter >= 7:
        # # 检测是否存在挂单，避免需要平仓时，存在挂单。
        # openOrders = binance_u_furture_get_openOrders(exchange)  # 查询当前所有挂单
        # openOrders = pd.DataFrame(openOrders, dtype='float')
        # # 整理数据
        # openOrders.rename(columns={'symbol': '交易对', 'orderId': '系统订单号'}, inplace=True)
        # print(openOrders)
        # ii = 0
        # if len(openOrders.index) != 0:
        #     for ind, row in openOrders.iterrows():
        #         ii += 1
        #         print('查询订单中', ind)
        #         symbol = row.iloc[1]
        #         binance_u_furture_DELETE_allOpenOrders(exchange, symbol)
        #         print(f'取消{symbol}存在的挂单成功')
        print('【3】-----亏损动态黑名单监测-----')
        # =====动态黑名单亏损5%进入
        s_time = time.time()
        positionside(exchange, percentage, profit_percentage, max_one_order_amount, price_precision, profit_record,
                     equity,
                     dingding_id, dingding_secret)
        print('盈亏_止损监测完成，花费时间：', time.time() - s_time)
        # exit()
        print('【4】-----止盈止损动态黑名单监测-----')
        # =====动态止盈动盈利超过n%启动监测
        s_time = time.time()
        position_profit(exchange, max_one_order_amount, price_precision, equity, dingding_id, dingding_secret)
        print('移动止盈监测完成，花费时间：', time.time() - s_time)
        print('【5】-----丁针监测-----')
        # =====动态黑名单亏损n%进入
        s_time = time.time()
        positionside_dingzhen(balance, df_current, long_profit_record, short_profit_record, equity,drawback, max_one_order_amount, price_precision,
                         ban_hours, robot_id, secret_key)
        print('丁针盈亏_监测完成，花费时间：', time.time() - s_time)

        print('【6】-----滚动逃顶监测-----')
        # =====动态黑名单亏损n%进入
        s_time = time.time()
        positionside_gundongtaoding(balance, df_current, roll_long_profit_record, roll_short_profit_record,equity,
                              max_one_order_amount, price_precision,
                              roll_ban_hours, robot_id, secret_key)
        print('滚动逃顶_盈亏监测完成，花费时间：', time.time() - s_time)
        # 检查是否接近小时顶部，如果是，则额外暂停一分钟
        current_time = time.localtime()
        minutes = current_time.tm_min
        if 0 <= minutes < 2 or 58 <= minutes < 60:
            print("接近整点，程序将休眠额外的1分钟...")
            time.sleep(60)  # 额外暂停一分钟
        # 本次循环结束
        # 时间补偿
        print('-' * sleep_time, '本次循环结束，%f秒后进入下一次循环' % sleep_time, '-' * sleep_time)
        print('\n')
        time.sleep(sleep_time)

if __name__ == '__main__':
    while True:
        try:
            run()
        except Exception as err:
            print('系统出错，10s之后重新运行，出错原因: ' + str(err))
            print(traceback.format_exc())
            time.sleep(10)
